// Load the application once the DOM is ready, using `jQuery.ready`:
$(function () {

    // Note Model
    // ----------

    var Note = Backbone.Model.extend({

        // Default attributes for the item.
        defaults: function () {
            return {
                id: Notes.nextId(),
                name: "New note",
                description: "",
                date: Date.now()
            };
        }

    });

    // Note Collection
    // ---------------

    // The collection of notes is backed by *localStorage* instead of a remote server

    var NoteList = Backbone.Collection.extend({

        // Reference to this collection's model.
        model: Note,

        // Save all of the items to local storage under namespace.
        localStorage: new Backbone.LocalStorage("notes-app"),

        // Save data to database.
        //url: 'api/notes',

        // We keep in sequential id, despite being saved by unordered
        // GUID in the database. This generates the next id number for new items.
        nextId: function () {
            if (this.url) return null;
            if (!this.length) return 1;
            return this.last().get('id') + 1;
        },

        // sorted by their original insertion id.
        comparator: function (note) {
            return parseInt(note.get("id"));
        },

        search: function (str) {
            // if(str == "") return this;

            var pattern = new RegExp(str, "gi");
            return _(this.filter(function (data) {
                data.trigger('show');
                if (pattern.test(data.get("description")) == false) {
                    data.trigger('hide');
                }
                ;
            }));

        }

    });

    // Create our global collection.
    var Notes = new NoteList;

    // Item View
    // --------------

    // The DOM element for a item...
    var NoteItemView = Backbone.View.extend({

        //... is a list tag.
        tagName: "li",
        className: "list-group-item hover",

        // Cache the template function for a single item.
        template: _.template($('#item-template').html()),

        // The DOM events specific to an item.
        events: {
            "click .destroy": "clear",
            "click": "select"
        },

        // The View listens for changes to its model, re-rendering.
        initialize: function () {
            this.listenTo(this.model, 'change', this.render);
            this.listenTo(this.model, 'destroy', this.remove);
            this.listenTo(this.model, 'select', this.select);
            this.listenTo(this.model, 'active', this.active);
            this.listenTo(this.model, 'hide', this.hide);
            this.listenTo(this.model, 'show', this.show);
        },

        // Re-render the titles of the item.
        render: function () {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        },

        // Remove the item, destroy the model.
        clear: function (e) {
            this.model.destroy();
            window.history.back();
        },

        // Click to select
        select: function () {
            this.active();
            app.navigate("notes/" + this.model.get('id'), {trigger: true});
        },

        // Active
        active: function () {
            this.$el.parent().find('.active').removeClass('active');
            this.$el.addClass('active');
        },

        hide: function () {
            this.$el.addClass('hide');
        },

        show: function () {
            this.$el.removeClass('hide');
        }

    });


    // list view

    var NoteListView = Backbone.View.extend({

        // Instead of generating a new element, bind to the existing skeleton of
        el: $("#note-list"),

        // Delegated events for creating new items, and clearing completed ones.
        events: {
            "click #new-note": "create",
            "keyup #search-note": "search"
        },
        // At initialization we bind to the relevant events on the
        // collection, when items are added or changed. Kick things off by
        // loading any preexistings that might be saved in *localStorage*.
        initialize: function () {
            this.listenTo(Notes, 'add', this.addOne);
            this.listenTo(Notes, 'reset', this.addAll);
            this.listenTo(Notes, 'all', this.render);
        },

        // Re-rendering the App just means refreshing the statistics -- the rest
        // of the app doesn't change.
        render: function () {

        },

        // Add a single item to the list by creating a view for it, and
        // appending its element to the `<ul>`.
        addOne: function (note) {
            var view = new NoteItemView({model: note});
            this.$el.find('#note-items').prepend(view.render().el);
        },

        // Add all items in the collection at once.
        addAll: function () {
            Notes.each(this.addOne, this);
        },

        create: function (e) {
            var note = new Note;
            Notes.create(note, {
                success: function () {
                    note.trigger('select');
                }
            });
        },

        search: function () {
            Notes.search($('#search-note').val());
        }

    });

    // note detail
    var NoteView = Backbone.View.extend({
        el: $("#note-detail"),

        // Cache the template function
        template: _.template($('#note-template').html()),

        // The DOM events specific to the textarea.
        events: {
            "keyup textarea": "updateOnKeyup",
        },

        initialize: function () {
            this.$el.html(this.template(this.model.toJSON()));
        },

        // update the model when update
        updateOnKeyup: function (e) {
            var name = '',
                description = $(e.target).val(),
                arr = description.split(/\r\n|\r|\n/g);
            arr.length && ( name = _.first(_.filter(arr, function (item) {
                return !!$.trim(item);
            })) );
            this.model.save({name: name, description: description});
        },

        close: function () {
            this.$el.unbind();
            this.$el.empty();
        }

    });


    var AppRouter = Backbone.Router.extend({
        routes: {
            "": "list",
            "notes/:id": "details"
        },

        initialize: function () {

        },

        list: function () {
            if (this.noteListView) return;
            this.noteListView = new NoteListView;
            var self = this;
            Notes.fetch({
                success: function () {
                    var id = app.requiredId || (Notes.length && Notes.at(Notes.length - 1).get('id'));
                    Notes.length && self.details(id) && app.navigate('notes/' + id);
                    !Notes.length && $('#new-note').trigger('click');
                }
            });
        },

        details: function (id) {
            app.requiredId = id;
            this.list();
            // close the note detail view
            if (this.noteView) this.noteView.close();
            // get the note
            this.note = Notes.get(id);
            if (this.note) {
                this.note.trigger('active');
                this.noteView = new NoteView({model: this.note});
            }
            return this;
        }

    });

    // Finally, we kick things off by creating the **App**.

    var app = new AppRouter();
    Backbone.history.start();

});
